package com.maweirdos.gulimall.search.thread;


import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: Maweirdos
 * @Date: 2024/4/7 20:11
 */
public class ThreadTest {

    // 创建线程池
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("开始=====");
        /**
         * 1、CompletableFuture.runAsync无返回值的线程方法执行
         * 2、CompletableFuture.supplyAsync.whenComplete 有返回值，并且能感知异常，但是没法修改返回数据
         * 3、CompletableFuture.supplyAsync.whenComplete 有返回值，并且能感知异常，可以修改返回的数据
         */
       //无返回值
       /*CompletableFuture.runAsync(()->{
            System.out.println("当前线程:"+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果"+i);
        },executor);*/

        // 有返回值，并且能感知异常，但是没法修改返回数据
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果" + i);
            return i;
        }, executor).whenComplete((res, exception) -> {
            System.out.println("异步任务完成了，结果是：" + res + "异常为：" + exception);
        }).exceptionally(throwable -> {
            return 10;
        });
        Integer integer = future.get();*/


        //使用handle则可以修改返回的数据
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果" + i);
            return i;
        }, executor).handle((res, exception) -> {
            System.out.println("异步任务完成了，结果是：" + res + "异常为：" + exception);
            if (res != null){
                return res*3;
            }
            if (exception != null){
                return 0;
            }
            return 0;
        });*/

        /**
         * 线程串行化，即执行完一个线程任务后，继续执行下一个线程任务
         * 默认沿用上一个任务的线程池，即方法为thenRun，thenAccept，thenApply，
         * 若加上Async(Runnable action)后，表示使用公用的 ForkJoinPool 线程池(不推荐使用公用线程池)，
         * 若加上Async(Runnable action,Executor executor): 使用自定义线程池(推荐)
         * 1、CompletableFuture.supplyAsync.thenRunAsync：不能获取上一步的执行结果
         * 2、CompletableFuture.supplyAsync.thenAcceptAsync：能接受上一步结果，但是无返回值
         * 3、CompletableFuture.supplyAsync.thenApplyAsync：能接受上一步结果，有返回值
         */
        //1、CompletableFuture.supplyAsync.thenRun：不能获取上一步的执行结果
        /*CompletableFuture.supplyAsync(()->{
            System.out.println("当前线程1--->" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程1启动");
            return i;

        },executor).thenRunAsync(() ->{
            System.out.println("线程2启动，无法获取上一步返回值");
        });*/

        //2、CompletableFuture.supplyAsync.thenAcceptAsync：能接受上一步结果，但是无返回值
        /*CompletableFuture.supplyAsync(()->{
            System.out.println("当前线程1--->" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程1启动");
            return i;

        },executor).thenAcceptAsync((res) ->{
            System.out.println("线程2启动，无返回值，但能获取获取上一步返回值:"+res);
        });
        System.out.println("结束=====");*/

        //3、CompletableFuture.supplyAsync.thenApplyAsync：能接受上一步结果，有返回值
        /*CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1--->" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程1启动");
            return i;

        }, executor).thenApplyAsync((res) -> {
            System.out.println("线程2启动，有返回值，能获取获取上一步返回值:" + res);
            return "我是串行线程2执行后的返回值";
        });
        System.out.println("打印结果："+future.get());*/


        /**
         * 任务组合，两个任务都要完成，完成后执行下一任务
         * 1、runAfterBothAsync:组合两个 future，不需要获取 future 的结果，只需两个future 处理完任务后,处理该任务。
         * 2、thenAcceptBothAsync:组合两个future，获取两个 future 任务的返回结果，然后处理任务，没有返回值。
         * 3、thenCombineAsync:组合两个 future,获取两个 future 的返回结果，并返回当前任务的返回值
         */
        /*CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1--->" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程1启动");
            return i;
        }, executor);

        CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2--->" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程2启动");
            return i;
        }, executor);*/

        //1、runAfterBothAsync:组合两个 future，不需要获取 future 的结果，只需两个future 处理完任务后,处理该任务。
        /*future01.runAfterBothAsync(future02,()->{
            System.out.println("线程三启动");
        },executor);*/

        //2、thenAcceptBothAsync:组合两个future，获取两个 future 任务的返回结果，然后处理任务，没有返回值。
        /*future01.thenAcceptBothAsync(future02,(f1,f2)->{
            System.out.println("线程3启动,无返回值，但是能获取线程1与线程2的值:"+f1+"-->"+f2);
        },executor);*/

        //3、thenCombineAsync:组合两个 future,获取两个 future 的返回结果，并返回当前任务的返回值
        /*CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            System.out.println("线程3启动,有返回值，能获取线程1与线程2的值:" + f1 + "和" + f2);
            return "线程3的返回值";
        }, executor);
        System.out.println(future.get());*/


        /**
         * 任务组合，两个任务只要完成其中一个就执行下一个任务
         * 1、runAfterEitherAsync:两个任务有一个执行完成，不需要获取 future 的结果，处理任务，也没有返回值。
         * 2、acceptEitherAsync:两个任务有一个执行完成，获取它的返回值，处理任务，没有新的返回值。
         * 3、applyToEitherAsync:两个任务有一个执行完成，获取它的返回值，处理任务并有新的返回值。
         */
       /* CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1--->" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("线程1启动");
            return i;
        }, executor);

        CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2--->" + Thread.currentThread().getId());
            int i = 10 / 2;
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("线程2启动");
            return i;
        }, executor);*/

        //1、runAfterEitherAsync:两个任务有一个执行完成，不需要获取 future 的结果，处理任务，也没有返回值。
        /*future01.runAfterEitherAsync(future02,()->{
            System.out.println("线程3启动");
        },executor);*/

        //2、acceptEitherAsync:两个任务有一个执行完成，获取它的返回值，处理任务，没有新的返回值。
        /*future01.acceptEitherAsync(future02,(res)->{
            System.out.println("线程3启动，无返回值，但是能获取线程1与线程2的值:"+res);
        },executor);*/

        //3、applyToEitherAsync:两个任务有一个执行完成，获取它的返回值，处理任务并有新的返回值。
        /*CompletableFuture<String> future = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("线程3启动，有返回值，能获取线程1与线程2的值,且比线程2快:" + res);
            return "线程3的返回值";
        }, executor);
        System.out.println(future.get());*/

        /**
         * 多任务组合
         * 1、allOf:等待所有任务完成
         * 2、anyOf:等待任意一个任务完成
         */
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("商品图片");
            return "商品图片";
        }, executor);

        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("商品属性");
            return "商品属性";
        }, executor);

        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("商品信息");
            return "商品信息";
        }, executor);

        // 1、allOf:等待所有任务完成
        /*CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
        // 调用get方法会阻塞等待所有任务完成
        allOf.get();*/

        // 2、anyOf:等待任意一个任务完成
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
        // 调用get方法会阻塞等待任意一个任务完成
        anyOf.get();

        System.out.println("线程结果"+futureImg.get()+"==="+futureAttr.get()+"==="+futureDesc.get());


        System.out.println("结束=====");
    }
}
